﻿//-----------------------------------------------------------------------------------------------------------
// Wbfs Engine (WBFSe) Project by Omega Frost 
// http://wbfse.codeplex.com/
//
// WBFSe is Licensed under the terms of the 
// Microsoft Reciprocal License (Ms-RL)
//-----------------------------------------------------------------------------------------------------------
using System;
using System.IO;
using WBFSe.FormatApi;
using WBFSe.IO;
using System.Collections.Generic;
using WBFSe.IO.Streams;
using System.Runtime.InteropServices;
using WBFSe.Builders.V1;
using WBFSe.Builders;
using WBFSe.OS;

namespace WBFSe.Formats
{
    /// <summary>
    /// Iso format reader
    /// </summary>
    class ISOReader : WbfsReader
    {
        bool isGame;

        /// <summary>
        /// Finds the container files in the array
        /// </summary>
        /// <param name="directory">The source folder</param>
        /// <param name="files">The files inside the source folder</param>
        /// <param name="filename">The desired filename</param>
        /// <exception cref="System.FileNotFoundException">If filename not found</exception>
        /// <exception cref="System.Exception">On operation failure</exception>
        public override void GetFiles(string directory, string[] files, string filename)
        {
            this.path = directory;
            this.filenames = new List<String>();
            this.filenames.Add(filename);
        }

        /// <summary>
        /// Parses the container
        /// </summary>
        /// <exception cref="System.Exception">On operation failure</exception>
        public override void ParseContainer()
        {
            this.version = 1;

            WbfsFileStream fs = new WbfsFileStream(this.path + this.filenames[0],
                FileMode.Open, FileAccess.Read, FileShare.Read);
            
            BuilderV1 builder = new BuilderV1(fs);

            if ((this.isGame = builder.Build(BuildFlags.UpdateHeaderOnly)))
            {
                this.gameName = builder.Name;
                this.gameCode = builder.Code;
                this.gameRegion = builder.Region;
                this.sectorUsage = builder.Usage;
                this.sectorSize = WbfsConstantsV1.WiiSectorSize;
                this.fileSize = fs.Size;
            }

            builder.Dispose();
            fs.Close();
        }

        /// <summary>
        /// Verifies if there's a game inside the container,
        /// should be used only by multi purpose containers
        /// such as RAR, ZIP, ISO. Avoid throwing exceptions
        /// inside this method, it can lead to poor engine
        /// performance on reading multiple files
        /// </summary>
        /// <returns>True if there's a game in the container</returns>
        public override bool IsGame()
        {
            // Current support for Wii isos only
            return this.isGame;
        }

        /// <summary>
        /// Changes the attributes of the game in the container's header
        /// </summary>
        /// <param name="name">The new name of the game</param>
        /// <param name="code">The new code of the game</param>
        /// <param name="region">The new region of the game</param>
        public override void ChangeHeader(string name, string code, Attributes.Region region)
        {
            // Do nothing...
        }

        /// <summary>
        /// Creates a Stream from the container files
        /// </summary>
        /// <param name="access">Desired acess</param>
        /// <param name="share">Desired sharing</param>
        /// <returns>Stream</returns>
        /// <exception cref="System.Exception">On operation failure</exception>
        protected override IWbfsStream GetStream(FileAccess access, FileShare share)
        {
            return new WbfsFileStream(this.path + this.filenames[0],
                FileMode.Open, access, share);
        }

        /// <summary>
        /// Cancels pending operations and closes streams
        /// </summary>
        protected override void Closing()
        {
            // Do nothing...
        }

        /// <summary>
        /// Disposes the container
        /// </summary>
        public override void Dispose()
        {
            // Do nothing...
        }
    }
}
